#ifndef _GUARD_H_
#define _GUARD_H_

#include "rads_base.hpp"
#include <cstdlib>
#include <cstdlib> 
#include <unistd.h>
#include <sstream>
#include <string>
#include <vector>
#include <thread>
#include <fstream>
#include <string>
#include <unistd.h>
#include <unordered_map>
#include <condition_variable>
#include <ros/ros.h>
#include <ros/time.h>
#include <std_msgs/String.h>

#include <rads/rads_guard.h>
#include <rads/rads_version.h>
#include <rads/rads_versions.h>

typedef struct
{
    rads::rads_versions kerner_vers;
    rads::rads_versions network_vers;
    bool ver_kernel_ok;
    bool ver_network_ok;
}VersionCheck;

// 查询进程是否开启
bool isProcessRunning(const std::string& processName) {
    std::string command = "top -b -n 1 | grep " + processName;
    char buffer[128];
    std::string result;
    std::string stream;
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe) {
        ROS_ERROR("Failed to run command");
        return false;
    }
    while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
        result += buffer;
    }
    pclose(pipe);
    if(result.empty()) return false;
    size_t found = result.find(result);
    if (found != std::string::npos) return true;
    return false;
}

// 查询节点服务是否开启
bool isNodeRunning(const std::string& nodeName) {
    std::string command = "rosnode list | grep \"" + nodeName + "\"";
    char buffer[128];
    std::string result;
    std::string stream;
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe) {
        ROS_ERROR("Failed to run command");
        return false;
    }
    while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
        result += buffer;
    }
    pclose(pipe);
    size_t found = result.find(nodeName);
    if (found != std::string::npos) return true;
    return false;
}

// about memery
std::unordered_map<std::string, long> parseMeminfo(const std::string& filePath) {
    std::unordered_map<std::string, long> meminfo;
    std::ifstream file(filePath);
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::string key;
        long value;
        if (iss >> key >> value) {
            meminfo[key] = value;
        }
    }
    return meminfo;
}

double calculateMemoryUsage(const std::unordered_map<std::string, long>& meminfo) {
    try {
        long memTotal = meminfo.at("MemTotal:");
        long memAvailable = meminfo.at("MemAvailable:");
        long memUsed = memTotal - memAvailable;
        return static_cast<double>(memUsed) / memTotal * 100.0;
    } catch (const std::out_of_range& e) {
        std::cerr << "Error: " << e.what() << " (key not found in meminfo)" << std::endl;
        return -1.0;
    }
}

// abount cpu
std::vector<long> parseCpuTimes(const std::string& line) {
    std::vector<long> cpuTimes(10, 0);
    std::istringstream iss(line);
    std::string cpuType;
    iss >> cpuType;
    if (cpuType == "cpu") {
        for (int i = 0; i < cpuTimes.size(); ++i) {
            iss >> cpuTimes[i];
        }
    } else if (cpuType.find("cpu") == 0) {
    }
    return cpuTimes;
}

double calculateCpuUsage(const std::vector<long>& prevCpuTimes, const std::vector<long>& currCpuTimes) {
    long prevIdle = prevCpuTimes[3] + prevCpuTimes[4]; // idle + iowait
    long currIdle = currCpuTimes[3] + currCpuTimes[4];
    long prevNonIdle = 0;
    long currNonIdle = 0;
    for (size_t i = 0; i < prevCpuTimes.size(); ++i) {
        if (i != 3 && i != 4) {
            prevNonIdle += prevCpuTimes[i];
            currNonIdle += currCpuTimes[i];
        }
    }
    long prevTotal = prevIdle + prevNonIdle;
    long currTotal = currIdle + currNonIdle;
    long totalDiff = currTotal - prevTotal;
    long idleDiff = currIdle - prevIdle;
    return (double)(totalDiff - idleDiff) / totalDiff * 100.0;
}

std::string getFirstLineOfFile(const std::string& filePath) {
    std::ifstream file(filePath);
    std::string line;
    if (std::getline(file, line)) {
        return line;
    } else {
        throw std::runtime_error("Could not read first line of file: " + filePath);
    }
}

// about ros

std::string getRobotVersion()
{
    std::string version;
    const char* ros_distro = std::getenv("ROS_DISTRO");
    if (ros_distro != nullptr) {
        std::string rosrobot(ros_distro);
        version = rosrobot;
    }
    return version;
}

// about os
// 读取文件内容到字符串中
std::string readFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        throw std::runtime_error("Unable to open file: " + filename);
    }
    std::string content((std::istreambuf_iterator<char>(file)),
                        (std::istreambuf_iterator<char>()));
    return content;
}

// 从文件内容中提取第一行
std::string getFirstLine(const std::string& filename) {
    std::string content = readFile(filename);
    std::size_t pos = content.find('\n');
    if (pos != std::string::npos) {
        return content.substr(0, pos);
    }
    return content;
}

// 获取系统版本（基于/etc/os-release文件）
std::string getSystemVersion() {
    try {
        std::string version = getFirstLine("/etc/os-release");
        return version;
    } catch (const std::exception& e) {
        std::cerr << "Error getting system version: " << e.what() << std::endl;
        return "Unknown";
    }
}

// 获取内核版本（基于/proc/version文件）
std::string getKernelVersion() {
    try {
        return getFirstLine("/proc/version");
    } catch (const std::exception& e) {
        std::cerr << "Error getting kernel version: " << e.what() << std::endl;
        return "Unknown";
    }
}

#endif
